home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / lfs / lfsLoad.c < prev    next >
C/C++ Source or Header  |  1991-05-29  |  10KB  |  337 lines

  1. /* 
  2.  * lfsLoad.c --
  3.  *
  4.  *    Code to handle the loading, checkpoint, and detaching of LFS file
  5.  *    system.
  6.  *
  7.  * Copyright 1989 Regents of the University of California
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /sprite/src/kernel/lfs/RCS/lfsLoad.c,v 1.8 91/05/29 14:12:37 mendel Exp $ SPRITE (Berkeley)";
  19. #endif /* not lint */
  20.  
  21. #include <sprite.h>
  22. #include <lfsInt.h>
  23. #include <stdlib.h>
  24. #include <rpc.h>
  25.  
  26. #include <string.h>
  27. #include <lfs.h>
  28.  
  29. static Fsdm_DomainOps lfsDomainOps = {
  30.     Lfs_AttachDisk,
  31.     Lfs_DetachDisk,
  32.     Lfs_DomainWriteBack,
  33.     Lfs_RereadSummaryInfo,
  34.     Lfs_DomainInfo,
  35.     Lfs_BlockAllocate,
  36.     Lfs_GetNewFileNumber,
  37.     Lfs_FreeFileNumber,
  38.     Lfs_FileDescInit,
  39.     Lfs_FileDescFetch,
  40.     Lfs_FileDescStore,
  41.     Lfs_FileBlockRead,
  42.     Lfs_FileBlockWrite,
  43.     Lfs_FileTrunc,
  44.     Lfs_DirOpStart,
  45.     Lfs_DirOpEnd
  46. };
  47.  
  48.  
  49.  
  50. /*
  51.  *----------------------------------------------------------------------
  52.  *
  53.  * LfsLoadFileSystem --
  54.  *
  55.  *    Load the checkpointed state of a file system and call the LFS
  56.  *    module attach routines to initialize a file system.
  57.  *
  58.  * Results:
  59.  *    SUCCESS if the file system was successfully loaded. 
  60.  *
  61.  * Side effects:
  62.  *    None.
  63.  *
  64.  *----------------------------------------------------------------------
  65.  */
  66.  
  67. ReturnStatus
  68. LfsLoadFileSystem(lfsPtr, flags)
  69.     Lfs        *lfsPtr;    /* File system to load checkpoint state. */
  70.     int      flags;    
  71. {
  72.     ReturnStatus    status;
  73.     LfsCheckPointHdr    checkPointHdr[2], *checkPointHdrPtr;
  74.     LfsCheckPointTrailer *trailerPtr;
  75.     LfsDiskAddr        diskAddr;
  76.     int            choosenOne, maxSize;
  77.     char        *checkPointPtr;
  78.     int            checkPointSize;
  79.  
  80.     Sync_LockInitDynamic(&(lfsPtr->checkPointLock), "LfsCheckpointLock");
  81.     /*
  82.      * Examine the two checkpoint areas to locate the checkpoint area with the
  83.      * newest timestamp.
  84.      */
  85.     LfsOffsetToDiskAddr(lfsPtr->superBlock.hdr.checkPointOffset[0],
  86.         &diskAddr);
  87.     status = LfsReadBytes(lfsPtr, diskAddr, sizeof(LfsCheckPointHdr),
  88.              (char *) (checkPointHdr+0));
  89.     if (status != SUCCESS) {
  90.     LfsError(lfsPtr, status, "Can't read checkpoint header #0");
  91.     return status;
  92.     }
  93.     LfsOffsetToDiskAddr(lfsPtr->superBlock.hdr.checkPointOffset[1],
  94.         &diskAddr);
  95.     status = LfsReadBytes(lfsPtr, diskAddr, sizeof(LfsCheckPointHdr), 
  96.         (char *) (checkPointHdr+1));
  97.     if (status != SUCCESS) {
  98.     LfsError(lfsPtr, status, "Can't read checkpoint header #1");
  99.     return status;
  100.     }
  101.     choosenOne = (checkPointHdr[0].timestamp<checkPointHdr[1].timestamp) ? 1 : 0;
  102.  
  103.     /*
  104.      * Read in the entire checkpoint region into a buffer.
  105.      */
  106.     maxSize = LfsBlocksToBytes(lfsPtr, 
  107.                 (lfsPtr->superBlock.hdr.maxCheckPointBlocks));
  108.     checkPointPtr = malloc(maxSize);
  109.  
  110. again:
  111.     LfsOffsetToDiskAddr(lfsPtr->superBlock.hdr.checkPointOffset[choosenOne],
  112.         &diskAddr);
  113.     status = LfsReadBytes(lfsPtr, diskAddr,  maxSize, checkPointPtr);
  114.     if (status != SUCCESS) {
  115.     free((char *) checkPointPtr);
  116.     LfsError(lfsPtr, status, "Can't read checkpoint region");
  117.     return status;
  118.     }
  119.     /*
  120.      * Verify checksum checkpoint region here.
  121.      */
  122.     checkPointHdrPtr = (LfsCheckPointHdr *) checkPointPtr;
  123.     trailerPtr = (LfsCheckPointTrailer *) 
  124.         (checkPointPtr + checkPointHdrPtr->size - 
  125.                 sizeof(LfsCheckPointTrailer));
  126.  
  127.     if (checkPointHdrPtr->timestamp != trailerPtr->timestamp) {
  128.     LfsError(lfsPtr, SUCCESS, "Bad checkpoint timestamps");
  129.     choosenOne = !choosenOne;
  130.     goto again;
  131.     }
  132.     printf("LfsLoad using checkpoint area %d with timestamp %d\n",
  133.     choosenOne, checkPointHdrPtr->timestamp);
  134.  
  135.     /*
  136.      * Install the domain if we can. 
  137.      */
  138.     status = Fsdm_InstallDomain(checkPointHdrPtr->domainNumber, 
  139.                 checkPointHdrPtr->serverID, lfsPtr->name, 
  140.                 flags, &(lfsPtr->domainPtr));
  141.     if (status != SUCCESS) {
  142.     free((char *) checkPointHdrPtr);
  143.     return (status);
  144.     }
  145.     lfsPtr->domainPtr->backendPtr = LfsCacheBackendInit(lfsPtr);
  146.     lfsPtr->domainPtr->domainOpsPtr = &lfsDomainOps;
  147.     lfsPtr->domainPtr->clientData = (ClientData) lfsPtr;
  148.  
  149.     /*
  150.      * Read in the current stats structure.
  151.      */
  152.     { 
  153.     Lfs_StatsVersion1 *statsPtr = (Lfs_StatsVersion1 *)(trailerPtr + 1);
  154.     if (statsPtr->version != 1) {
  155.         printf("LfsLoad: Bad stats version number %d\n", statsPtr->version);
  156.     }
  157.     bcopy ((char *) statsPtr, (char *) &lfsPtr->stats, 
  158.         sizeof(lfsPtr->stats));
  159.     }
  160.     checkPointPtr = checkPointPtr + sizeof(LfsCheckPointHdr);
  161.     checkPointSize =  ((char *)trailerPtr) - checkPointPtr;
  162.     /*
  163.      * Process the checkpoint for each region by  calling segment attach
  164.      * procedures for the modules doing segment I/O.
  165.      */
  166.  
  167.     status = LfsSegAttach(lfsPtr, checkPointPtr, checkPointSize);
  168.  
  169.     if (status != SUCCESS) {
  170.     free((char *) checkPointHdrPtr);
  171.     return status;
  172.     }
  173.  
  174.     /*
  175.      * Setup checkPoint data structure for next checkpoint operation. We use
  176.      * the buffer we allocated and set the nextRegion to be the one we
  177.      * didn't load from. Also set the timestamp into the future.
  178.      */
  179.     lfsPtr->checkPoint.timestamp = checkPointHdrPtr->timestamp+1;
  180.     lfsPtr->checkPoint.nextArea = !choosenOne;
  181.     lfsPtr->checkPoint.buffer = (char *) checkPointHdrPtr;
  182.     lfsPtr->checkPoint.maxSize = maxSize;
  183.  
  184.     /*
  185.      * Fill in the checkPointHdrPtr will the fields that don't change
  186.      * between checkpoints.
  187.      */
  188.     checkPointHdrPtr->timestamp = lfsPtr->checkPoint.timestamp;
  189.     checkPointHdrPtr->size = 0;
  190.     checkPointHdrPtr->version = 1;
  191.     bzero(checkPointHdrPtr->domainPrefix,
  192.         sizeof(checkPointHdrPtr->domainPrefix));
  193.     (void)strncpy(checkPointHdrPtr->domainPrefix, lfsPtr->name, 
  194.             sizeof(checkPointHdrPtr->domainPrefix)-1);
  195.     checkPointHdrPtr->domainNumber = lfsPtr->domainPtr->domainNumber;
  196.     checkPointHdrPtr->attachSeconds = Fsutil_TimeInSeconds();
  197.     checkPointHdrPtr->detachSeconds = checkPointHdrPtr->attachSeconds;
  198.     checkPointHdrPtr->serverID = rpc_SpriteID;
  199.  
  200.     return status;
  201. }
  202.  
  203. /*
  204.  *----------------------------------------------------------------------
  205.  *
  206.  * LfsDetachFileSystem --
  207.  *
  208.  *    Detach a file system.
  209.  *
  210.  * Results:
  211.  *    SUCCESS if the file system was successfully detach. 
  212.  *
  213.  * Side effects:
  214.  *    None.
  215.  *
  216.  *----------------------------------------------------------------------
  217.  */
  218.  
  219. ReturnStatus
  220. LfsDetachFileSystem(lfsPtr)
  221.     Lfs        *lfsPtr;    /* File system to load checkpoint state. */
  222. {
  223.     ReturnStatus    status;
  224.  
  225.  
  226.     (*lfsPtr->checkpointIntervalPtr) = 0;  /* Stop the timer checkpointer. */
  227.  
  228.     status = LfsCheckPointFileSystem(lfsPtr, LFS_CHECKPOINT_DETACH);
  229.  
  230.     status = LfsSegDetach(lfsPtr);
  231.  
  232.     free(lfsPtr->checkPoint.buffer);
  233.     return status;
  234. }
  235. #define    LOCKPTR &lfsPtr->checkPointLock
  236.  
  237.  
  238. /*
  239.  *----------------------------------------------------------------------
  240.  *
  241.  * LfsCheckPointFileSystem --
  242.  *
  243.  *    Checkpoint the state of a file system by calling the LFS
  244.  *    module attach routines.
  245.  *
  246.  * Results:
  247.  *    SUCCESS if the file system was successfully checkpointed. 
  248.  *
  249.  * Side effects:
  250.  *    None.
  251.  *
  252.  *----------------------------------------------------------------------
  253.  */
  254.  
  255. ReturnStatus
  256. LfsCheckPointFileSystem(lfsPtr, flags)
  257.     Lfs        *lfsPtr;    /* File system to be checkpointed. */
  258.     int flags;        /* Flags for checkpoint. */
  259. {
  260.     LfsCheckPointHdr    *checkPointHdrPtr;
  261.     int            size, blocks, bytes;
  262.     LfsCheckPointTrailer *trailerPtr;
  263.     LfsDiskAddr        diskAddr;
  264.     ReturnStatus    status;
  265.     char        *bufferPtr;
  266.  
  267.     bufferPtr = lfsPtr->checkPoint.buffer;
  268.     checkPointHdrPtr = (LfsCheckPointHdr *) bufferPtr;
  269.     if (flags & LFS_CHECKPOINT_CLEANER) { 
  270.     /* 
  271.      * The cleaner uses it own checkpoint buffer. Allocate it 
  272.      * and initialized the LfsCheckPointHdr with the values that
  273.      * don't change. 
  274.      */
  275.     bufferPtr = malloc(lfsPtr->checkPoint.maxSize);
  276.     bcopy((char *) checkPointHdrPtr, bufferPtr, 
  277.         sizeof(LfsCheckPointHdr));
  278.     checkPointHdrPtr = (LfsCheckPointHdr *) bufferPtr;
  279.  
  280.     }  
  281.  
  282.  
  283.     status = LfsSegCheckPoint(lfsPtr, flags, (char *)(checkPointHdrPtr+1),
  284.                 &size);
  285.     if ((status != SUCCESS) || (size < 0)) {
  286.     if (bufferPtr != lfsPtr->checkPoint.buffer) {
  287.         free(bufferPtr);
  288.     }
  289.     return status;
  290.     }
  291.     LOCK_MONITOR;
  292.     /*
  293.      * Fill in check point header and trailer.
  294.      */
  295.     checkPointHdrPtr->timestamp = LfsGetCurrentTimestamp(lfsPtr);
  296.     checkPointHdrPtr->size = size + sizeof(LfsCheckPointHdr) + 
  297.              sizeof(LfsCheckPointTrailer);
  298.     checkPointHdrPtr->version = 1;
  299.     checkPointHdrPtr->detachSeconds = Fsutil_TimeInSeconds();
  300.     trailerPtr = (LfsCheckPointTrailer *) 
  301.         (bufferPtr + size + sizeof(LfsCheckPointHdr));
  302.     trailerPtr->timestamp = checkPointHdrPtr->timestamp;
  303.     trailerPtr->checkSum = 0;
  304.  
  305.     /*
  306.      * Append the stats to the checkpoint regions.
  307.      */
  308.     bytes = checkPointHdrPtr->size + sizeof(Lfs_Stats);
  309.     blocks = LfsBytesToBlocks(lfsPtr, bytes);
  310.     LFS_STATS_ADD(lfsPtr->stats.checkpoint.totalBlocks, blocks);
  311.     LFS_STATS_ADD(lfsPtr->stats.checkpoint.totalBytes, bytes);
  312.     bcopy ((char *) &lfsPtr->stats, (char *) (trailerPtr + 1), 
  313.         sizeof(lfsPtr->stats));
  314.     LfsOffsetToDiskAddr(
  315.     lfsPtr->superBlock.hdr.checkPointOffset[lfsPtr->checkPoint.nextArea],
  316.         &diskAddr);
  317.     status = LfsWriteBytes(lfsPtr, diskAddr, 
  318.     LfsBlocksToBytes(lfsPtr, blocks), (char *) checkPointHdrPtr);
  319.     if (status == SUCCESS) {
  320.     /*
  321.      * Set the file system up to use the other checkpoint buffer next time.
  322.      */
  323.     lfsPtr->checkPoint.nextArea = !lfsPtr->checkPoint.nextArea;
  324.     } else {
  325.     UNLOCK_MONITOR;
  326.     LfsError(lfsPtr, status, "Can't write checkpoint region\n");
  327.     LOCK_MONITOR;
  328.     }
  329.     UNLOCK_MONITOR;
  330.     LfsSegCheckPointDone(lfsPtr, flags);
  331.     if (bufferPtr != lfsPtr->checkPoint.buffer) {
  332.     free(bufferPtr);
  333.     }
  334.     return status;
  335. }
  336.  
  337.